package com.swdegao.iot.netty.udp.server.channelhandler;


import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

import java.util.List;

import org.apache.commons.codec.binary.Hex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.alibaba.fastjson.JSON;
import com.swdegao.iot.SwdegaoIotMgtServerApplication;
import com.swdegao.iot.netty.entity.ApplicationSubscribe;
import com.swdegao.iot.netty.entity.CallBackData;
import com.swdegao.iot.netty.entity.HandlerMessage;
import com.swdegao.iot.netty.entity.ImeiInfo;
import com.swdegao.iot.netty.entity.MyProps;
import com.swdegao.iot.netty.entity.Parameter;
import com.swdegao.iot.netty.entity.UpData;
import com.swdegao.iot.netty.utils.RedisUtils;

/**
 * 用于存储数据包、更新redis中数据
 * @Author:只会走路的小鸟
 * @Date: Created in 8:20 2018\10\26 0001
 */
public class SaveMessgaeHandler extends SimpleChannelInboundHandler<HandlerMessage> {

	@Autowired
    private RedisUtils redisUtils = SwdegaoIotMgtServerApplication.getBean(RedisUtils.class);
	//定义一个全局的记录器，通过LoggerFactory获取
    private final static Logger logger = LoggerFactory.getLogger(SaveMessgaeHandler.class);

	@Override
	protected void channelRead0(ChannelHandlerContext cxt, HandlerMessage msg) throws Exception {
		String imei = msg.getImei();

		try {

			Byte actiontype = msg.getActionTpye();

			UpData upData = new UpData();
			long nowtime = System.currentTimeMillis();
			upData.setCreatetime(nowtime);
			upData.setImei(imei);

		    byte[] receiveMsgBytes = new byte[msg.getRecevieMsg().capacity()];
		    msg.getRecevieMsg().getBytes(msg.getRecevieMsg().readerIndex(), receiveMsgBytes);

		    upData.setUpData(Hex.encodeHexString(receiveMsgBytes));
			String callbackUrl = "";
			//imei信息以hash形式存储（key,hashkey,value）
			if(redisUtils.hmhave(Parameter.imei_info,imei)){//已经存储

				ImeiInfo imeiInfo = JSON.parseObject(redisUtils.hmGet(Parameter.imei_info,imei).toString(), ImeiInfo.class);
				msg.setApplicationSubscribe(imeiInfo.getApplicationSubscribe());//订阅的信息
				callbackUrl = (imeiInfo.getApplicationSubscribe()!=null&&imeiInfo.getApplicationSubscribe().size()>0) ? imeiInfo.getApplicationSubscribe().get(0).getCallbackurl().toString() : "";
				if(actiontype==(byte)0x81){
					//注册、更新时间、更新心跳周期
					int heartbeat_cycle = 0;
					try {
						heartbeat_cycle = receiveMsgBytes[0];
					} catch (Exception e) {
						// TODO: handle exception
						heartbeat_cycle = Parameter.heartbeat_cycle;
					}
					int heartbeat_registered_num = imeiInfo.getHeartbeat_registered_num();
					heartbeat_registered_num++;
					imeiInfo.setOnlineLastTime(nowtime);
					imeiInfo.setHeartbeat_registered_num(heartbeat_registered_num);
					imeiInfo.setHeartbeat_cycle(heartbeat_cycle);
					imeiInfo.setOnlineStatus("1");
					imeiInfo.setcType("UDP");
					redisUtils.hmSet(Parameter.imei_info, imei, JSON.toJSONString(imeiInfo));

				}

				if(actiontype==(byte)0x83){
					//判断问题是否失效
					String downDataId  = imeiInfo.getDownDataId();

					if(null!=downDataId && !"".equals(downDataId)){
						int OutTime = 0;
						try {
							OutTime = imeiInfo.getOutTime();
						} catch (Exception e) {
							// TODO: handle exception
							OutTime = Parameter.outtime_hear;
						}
						Long differenceTime = (nowtime - imeiInfo.getRequestLastTime())/1000 - OutTime;
						if(differenceTime>0){//问题已经过期、将hash中Imei_info更新、下次无需再验证问题失效逻辑
							imeiInfo.setDownDataId("");
							imeiInfo.setRequestLastTime((long)0);
							redisUtils.hmSet(Parameter.imei_info, imei, JSON.toJSONString(imeiInfo));
						}else{//问题没有过期、在updata记录downDataId信息，且单独记录本问题回复答案
							upData.setDownDataId(imeiInfo.downDataId);
							msg.setDownDataId(imeiInfo.downDataId);
							//更新问题最后响应时间
							imeiInfo.setRequestLastTime(nowtime);
							redisUtils.hmSet(Parameter.imei_info, imei, JSON.toJSONString(imeiInfo));
							//存储问题答案
							redisUtils.lPush(imei+"_"+upData.getDownDataId()+Parameter.imei_info_requestdata,JSON.toJSONString(upData));//存储所有updata数据
						}
					}
				}

			}else{
				//直接往hash中添加
				ImeiInfo imeiInfo = new ImeiInfo();
				imeiInfo.setOnlineLastTime(nowtime);
				imeiInfo.setOnlineStatus("1");
				imeiInfo.setcType("UDP");
				imeiInfo.setImei(imei);
				imeiInfo.setOutTime(Parameter.outtime_hear);
				imeiInfo.setHeartbeat_registered_num(0);
				imeiInfo.setHeartbeat_delay_num(0);
				int heartbeat_cycle = 0;
				if(actiontype==(byte)0x81){
					try {
						heartbeat_cycle = receiveMsgBytes[0];
					} catch (Exception e) {
						// TODO: handle exception
						heartbeat_cycle = Parameter.heartbeat_cycle;
					}
					imeiInfo.setHeartbeat_cycle(heartbeat_cycle);
				}

				//msg.setApplicationSubscribe(imeiInfo.getApplicationSubscribe());
				redisUtils.hmSet(Parameter.imei_info, imei, JSON.toJSONString(imeiInfo));
			}


//			redisUtils.lPush(imei+Parameter.imei_info_updata,JSON.toJSONString(upData));//存储所有updata数据
			//将推送数据存储到redis中
			try {
				if ((actiontype == (byte) 0x83 || actiontype == (byte) 0x85) && receiveMsgBytes.length>5 && receiveMsgBytes[4] == (byte)0x60) {// 走推送的流程
					//callbackUrl = "".equals(callbackUrl)?myProps.getMycallbackurl() : callbackUrl;
					CallBackData callBackData = new CallBackData();
					callBackData.setImei(imei);
					callBackData.setCreatetime(nowtime);
					callBackData.setUrl(callbackUrl);
					callBackData.setCallbackNum(0);
					callBackData.setUpData(upData.getUpData());
					redisUtils.lPush(imei+Parameter.imei_callbackurl,JSON.toJSONString(callBackData));//存储所有updata数据
				}
			} catch (Exception e) {
				// TODO: handle exception
			}

		} catch (Exception e) {
			// TODO: handle exception
			logger.error(imei+"#######"+e.getMessage());
		}

	//将message继续往下传递
		cxt.fireChannelRead(msg);
	}

	@Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // (7)
	    	Channel incoming = ctx.channel();
			logger.info("client "+incoming.remoteAddress()+"异常"+cause.getMessage());
	        // 当出现异常就关闭连接
	        cause.printStackTrace();
	        //ctx.close();
	    }

}
